{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# How to use a QComponent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For convenience, let's begin by enabling [automatic reloading of modules](https://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html?highlight=autoreload) when they change."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, let's import Qiskit Metal:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import qiskit_metal as metal\n",
    "from qiskit_metal import designs, draw\n",
    "from qiskit_metal import MetalGUI, Dict, open_docs\n",
    "\n",
    "%metal_heading Welcome to Qiskit Metal!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Just as we did in the \"Start Here\" notebook, we'll open the Qiskit Metal GUI and work with simple planar designs:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design = designs.DesignPlanar()\n",
    "gui = MetalGUI(design)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's load a QComponent with all default options, corresponding to a transmon qubit. This particular QComponent is stored in the library qiskit_metal.qlibrary.qubits and we'll create a new object of the class TransmonPocket. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Select a QComponent to create (The QComponent is a python class named `TransmonPocket`)\n",
    "from qiskit_metal.qlibrary.qubits.transmon_pocket import TransmonPocket\n",
    "\n",
    "# Create a new qcomponent object  \n",
    "q1 = TransmonPocket(design)\n",
    "gui.rebuild()  # rebuild the design and plot "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We see that this QComponent consists of two large metallic pads with a thin strip of metal connecting them, corresponding to a Josephson Junction. The transmon qubit is centered at the origin by default. In the GUI, we can see that the ID assigned to our QComponent is \"1\" and that the QComponent class is \"Transmon Pocket.\" \n",
    "\n",
    "Note that since we didn't give the Qcomponent an explicit name, one was assigned automatically (\"Pocket_1\") which we can also see in the GUI. Taking a look at the actual qcomponent python script, we see that there is a \"short name\" defined in the qcomponent metadata (short_name = \"Pocket\" in the dictionary), which is where this name comes from. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is easy to give a specific name to a Qcomponent object. We can delete the QComponent \"Pocket_1\" by just clicking the \"Delete all\" button in the Qiskit Metal GUI. Alternatively, this can done by executing the following command, which deletes all components in the design (more on deleting later in this tutorial): "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Delete all QComponents in our design, which in this case is just the transmon pocket \"Pocket_1\"\n",
    "design.delete_all_components()\n",
    "gui.rebuild()  # rebuild the design and plot "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then, we can create the same transmon pocket with the name \"Q1\" by typing the command:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create a new qcomponent object with name 'Q1' \n",
    "q1 = TransmonPocket(design, 'Q1')\n",
    "gui.rebuild()  # rebuild the design and plot "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The QComponent we've just created as a name \"Q1\" and a Qcomponent ID of 2, since an ID of 1 was already used for the now-deleted \"Pocket_1\" object. It is worth noting that the QComponent we've just created is not functional yet; it's just two rectangular metal pads with a thin strip of metal connecting them. In order for a QComponent to be functional in an actual design, we will need to add a few additional things, such as qpins defining where the transmon pocket connects to coplanar waveguides (CPWs). We will discuss this in more detail later in the tutorial. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# QComponent Default Options"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "QComponents come with some default options, which are used in the make function of the qcomponent to create the qgeometry that you see in the GUI. These options are parsed by Qiskit Metal, and can be changed using either the GUI or the script API. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can see what the options and other parameters are for our Qcomponent by typing the following command:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "q1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can see the full list of template options for the class by typing this command:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "TransmonPocket.get_template_options(design)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Modifying the Options"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can modify the QComponent by changing the default options. This can be done using either the python API or the GUI. Here's an example where we'll move the transmon from (0,0) to (2,2), while also modifying the pad height and width:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Change options\n",
    "q1.options.pos_x = '2.0 mm'\n",
    "q1.options.pos_y = '2.0 mm'\n",
    "q1.options.pad_height = '250 um'\n",
    "q1.options.pad_width  = '300 um'\n",
    "\n",
    "# Update the geoemtry and render to the gui, since we changed the options\n",
    "gui.rebuild()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Copying a QComponent "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can copy a QComponent using the \"design.copy_qcomponent\" command. Let's make a copy of our transmon qubit, which is located at (2,2) and place the copy at (-2,2):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Copy q1 and place the new Qcomponent (\"q1_copy\") at (-2,2):\n",
    "q1_copy = design.copy_qcomponent(q1, 'Q1_copy')\n",
    "q1_copy.options['pos_x']='-2.0mm'\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also copy multiple QComponents at the same time. For example, let's suppose we want to take our two transmon qubits at (-2,2) and (2,2) and create copies which are located at (-2,2) and (-2,2):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Let's copy the two QComponents and change the y-coordinates of the copies to both be -2:\n",
    "newcopies = design.copy_multiple_qcomponents([q1, q1_copy], ['Q3', 'Q4'], [dict(pos_y='-2.0mm'), dict(pos_y='-2.0mm')])\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we have four transmon qubits located at the corners of a square: (-2,-2), (-2,2), (2,2) and (2,-2). "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Deleting a QComponent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We saw in an earlier example how to delete all QComponents in a design using the either the \"design.delete_all_components\" command or by using the \"Delete all\" button in the GUI. But what if we only want to delete specific QComponents without deleting everything in a design? \n",
    "\n",
    "We can delete a specific qcomponent using either the GUI or the python API. If you wish to remove a specific QComponent, you can do so using the \"delete_component\" or \"_delete component\" commands. The first takes the string reference to a Qcomponent, while the second takes an integer reference to a QComponent. Suppose we want to remove qubit 'Q1'. Presently, we do not need to pass a Boolean corresponding to whether we want to force the delete (true=1) even if the component has dependencies, or whether the deletion should not be executed in the event the QComponent does have dependencies (false=0). The bool option is for future potential possibilities of having Qcomponents with dependencies. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.delete_component('Q1')\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also delete without checking for QComponent dependencies at all. In this case, we pass only the QComponent ID. As an example, we can force delete 'Q1_copy\" which has QComponent ID=3 by typing:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design._delete_component(3)\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Renaming a QComponent "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the first example in this notebook, we created a QComponent named \"Pocket_1\" then deleted it and created one with the name \"Q1.\" One can also simply rename a QComponent without deleting it and creating a new one. We can rename a QComponent by using the \"design_rename.component\" command. For example, let's rename \"Q3\" and \"Q4\" to \"Q_three\" and \"Q_four\", respectively. Note that \"Q3\" has a QComponent ID of 4, while \"Q4\" has a Qcomponent ID of 5. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.rename_component(4,'Q_three') # rename \"Q3\" to \"Q_three\"\n",
    "design.rename_component(5,'Q_four') # rename \"Q4\" to \"Q_four\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Overwriting a QComponent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In order to enable component overwrite of qcomponents with the same name, we can use the following command:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.overwrite_enabled = True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This allows for the qcomponent to be modified and re-built without having to delete it. Without this line, a qcomponent would have to be deleted before recreating it with different options. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Closing the Qiskit Metal GUI"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.main_window.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
